"""
a1:  区间值模糊数 格式为([],[])

self.q: q值
self.x: 一个参数时所用的变量,在dombi中，x >= 1

a2:     区间值模糊数 格式为([],[])

编写时间:2022/7/29
编写人:万骏哲
参考文献:Some Dombi aggregation of Q‐rung orthopair
fuzzy numbers in multiple‐attribute decision
making
"""

import os
from Utilities.AutoGetOperator.selectPackage import get_func

Operator_IVQ_ROFS=get_func(r'Operators/OperationOperators/OperatorIVQROF.py','Operator_IVQ_ROFS')

class Quasi(Operator_IVQ_ROFS):

    def add(self, a1, a2, q=0, *waste1, **waste2):
        """
            funciton    : 区间值广义正交模糊集的 和 运算
            a1          : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2          : 一个模糊集, 形式:（[x,y]，[x,y]）
            return      : 加法结果, 形式:（[x,y]，[x,y]）
        """
        u_1_f, u_1_r, v_1_f, v_1_r = *a1[0], *a1[1]
        u_2_f, u_2_r, v_2_f, v_2_r = *a2[0], *a2[1]
        if q <= 0:
            q = self.q
        u_f = (u_1_f ** q + u_2_f ** q - (u_1_f ** q) * (u_2_f ** q)) ** (1 / q)
        u_r = (u_1_r ** q + u_2_r ** q - (u_1_r ** q) * (u_2_r ** q)) ** (1 / q)
        v_f = (v_1_f) * (v_2_f)
        v_r = (v_1_r) * (v_2_r)
        return ([u_f, u_r], [v_f, v_r])

    def multi(self, a1, a2, q=0, *waste1, **waste2):
        """
            funciton    : 区间值广义正交模糊集的 积 运算
            a1          : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2          : 一个模糊集, 形式:（[x,y]，[x,y]）
            return      : 乘法结果, 形式:（[x,y]，[x,y]）
        """
        u_1_f, u_1_r, v_1_f, v_1_r = *a1[0], *a1[1]
        u_2_f, u_2_r, v_2_f, v_2_r = *a2[0], *a2[1]
        if q <= 0:
            q = self.q
        u_f = (u_1_f) * (u_2_f)
        u_r = (u_1_r) * (u_2_r)
        v_f = (v_1_f ** q + v_2_f ** q - (v_1_f ** q) * (v_2_f ** q)) ** (1 / q)
        v_r = (v_1_r ** q + v_2_r ** q - (v_1_r ** q) * (v_2_r ** q)) ** (1 / q)
        return ([u_f, u_r], [v_f, v_r])

    def kmulti(self, a, k, q=0, *waste1, **waste2):
        """
            function : 区间值广义正交模糊集的 数乘 运算
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            k        : ka 的常数 k
            return   : 数乘 运算法则 的值，形式：（[x,y]，[x,y]）
        """
        u_a_f, u_a_r, v_a_f, v_a_r = *a[0], *a[1]
        if q <= 0:
            q = self.q
        u_f = (1 - (1 - (u_a_f) ** q) ** k) ** (1 / q)
        u_r = (1 - (1 - (u_a_r) ** q) ** k) ** (1 / q)
        v_f = (v_a_f) ** k
        v_r = (v_a_r) ** k
        return ([u_f, u_r], [v_f, v_r])

    def pow(self, a, k, q=0, *waste1, **waste2):
        """
            function : 区间值广义正交模糊集的 乘方 运算
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            k        : ka 的常数 k
            return   : 乘方 运算法则 的值，形式：（[x,y]，[x,y]）
        """
        u_a_f, u_a_r, v_a_f, v_a_r = *a[0], *a[1]
        if q <= 0:
            q = self.q
        v_f = (1 - (1 - (v_a_f) ** q) ** k) ** (1 / q)
        v_r = (1 - (1 - (v_a_r) ** q) ** k) ** (1 / q)
        u_f = (u_a_f) ** k
        u_r = (u_a_r) ** k
        return ([u_f, u_r], [v_f, v_r])

class QuasiWA(Quasi):
    def getResult(self):
        data_list = self.data_list
        weight_list = self.weight_list
        q = self.q
        res = self.kmulti(data_list[0], weight_list[0],q)
        n = len(weight_list)
        for idx in range(n):
            if idx == 0:
                continue
            res = self.add(res, self.kmulti(data_list[idx], weight_list[idx], q))
        return res

class QuasiGA(Quasi):
    def  getResult(self):
        data_list=self.data_list
        weight_list=self.weight_list
        q=self.q
        n = len(data_list)-1
        result = self.pow(data_list[0], weight_list[0],q)
        for i in range(1,n+1):
            temp = self.pow(data_list[i], weight_list[i],q)
            result = self.multi(result, temp,q)
        return result

class QuasiQWA(Quasi):
    def  getResult(self):
        data_list=self.data_list
        weight_list=self.weight_list
        q=self.q
        n = len(data_list)-1
        result = self.pow(data_list[0], 2,q)
        for i in range(1,n+1):
            temp1 = self.kmulti(self.pow(data_list[i], 2,q),weight_list[i],q)
            result = self.add(result, temp1,q)
            result=self.pow(result,1/2,q)
        return result

class QuasiRWA(Quasi):
    def  getResult(self):
        data_list=self.data_list
        weight_list=self.weight_list
        a=self.a
        q=self.q
        n = len(data_list)-1
        result = self.pow(data_list[0], a,q)
        for i in range(1,n+1):
            temp1 = self.kmulti(self.pow(data_list[i], a,q),weight_list[i],q)
            result = self.add(result, temp1,q)
            result=self.pow(result,1/a,q)
        return result



class QuasiOWA(Quasi):

    def getResult(self):
        data_list = self.sortdata()
        weight_list = self.weight_list
        q = self.q
        n = len(data_list)
        res = self.kmulti(data_list[0], weight_list[0])
        for idx in range(n):
            if idx == 0:
                continue
            res = self.add(res, self.kmulti(data_list[idx], weight_list[idx], q))
        return res

if __name__ == '__main__':
    data_list = [([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
                 ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]), ([0.95, 0.06], [0.19, 0.1])]
    weight_list = [0.1, 0.2, 0.3, 0.1, 0.3],
    # Pa = A(data_list)
    Pa = QuasiWA(data_list)
    # Pa = WA(data_list,weight_list)
    # Pa = WGA(data_list,weight_list)
    # Pa = OWA(data_list,weight_list)
    print(Pa.getResult())